perm filename CHTOPX.TEX[MF,ALS] blob sn#759255 filedate 1984-06-27 generic text, type T, neo UTF8
\input webmac
% This program is not copyrighted and can be used freely.
% Version 0 was implemented in May 1983.

% Here is TeX material that gets inserted after \input webhdr
\def\hang{\hangindent 3em\indent\ignorespaces}
\def\TeX{T\hbox{\hskip-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}
\font\ninerm=cmr9
\let\mc=\ninerm % medium caps for names like PASCAL
\def\PASCAL{{\mc PASCAL}}

\def\(#1){} % this is used to make module names sort themselves better
\def\9#1{} % this is used for sort keys in the index

\def\title{CH\lowercase{to}PX}
\def\contentspagenumber{1}
\def\topofcontents{\null
	\def\titlepage{F} % include headline on the contents page
	\def\rheader{\mainfont\hfil \contentspagenumber}
	\vfill
	\centerline{\titlefont The {\ttitlefont CHtoPX} processor}
	\vskip 15pt
	\centerline{(Version 1, October 1983)}
	\vfill}
\def\botofcontents{\vfill
	\centerline{\hsize 5in\baselineskip9pt
		\vbox{\ninerm\noindent
		The preparation of this report
		was supported in part by the National Science
		Foundation under grants IST-8201926 and MCS-7723738,
		and by the System Development Foundation. `\TeX' is a
		trademark of the American Mathematical Society.}}}
\count0=\contentspagenumber \advance\count0 by 1

\N1.  Introduction.
The \.{CHtoPX} utility program converts \TeX\ raster pixel (``\.{CHR}'')
files into character pixel (``\.{PXL}'') files.
The \.{CHR} file input by this program can be edited with
a normal text editor, and the result can be converted back to \.{PXL}
format. The companion program \.{PXtoCH} will convert a \.{PXL} file
into a \.{CHR} file.

The first \.{CHtoPX} program was designed by Lynn Ruggles in the spring of
1983.  The programs \.{TFtoPL} and \.{PLtoTF} had a significant effect on
the evolution of the present code.

A \.{CHR} file may contain raster information for as many as 128 characters
and as few as 0 characters. An exception to these rules is
planned for oriental fonts;
such fonts, however, are not allowed by this version of \.{CHtoPX}.

The \\{banner} string defined here should be changed whenever \.{CHtoPX}
gets modified.

\Y\P\D \37$\\{banner}\S\.{\'This\ is\ CHtoPX,\ Version\ 1\'}$\C{printed when
the program starts}\par
\fi

\M2. This program is written entirely in standard \PASCAL, except that
it occasionally has lower case letters in strings that are output.
Such letters can be converted to upper case if necessary. The input is read
from \\{chr\_file}, and the output is written on \\{pxl\_file}; error messages
and
other remarks are written on the \\{error\_file}, which the user may
choose to assign to the terminal if the system permits it.

Each character ends with an \\{page\_marker}, which
is set to chr(12) (cntl-L). This character can be changed for systems which
do not use cntl-L's in file formats. Whatever character is chosen should be
one that will not appear at the beginning of a line. This restriction
excludes all of the letters, and the symbols +, -, :, and blank.


The term \\{print} is used instead of \\{write} when this program writes on
the \\{error\_file}, so that all such output can be easily deflected.

\Y\P\D \37$\\{print}(\#)\S\\{write}(\\{error\_file},\39\#)$\par
\P\D \37$\\{print\_ln}(\#)\S\\{write\_ln}(\\{error\_file},\39\#)$\par
\Y\P\4\&{program}\1\  \37$\\{CHtoPX}(\\{chr\_file},\39\\{pxl\_file},\39\\{error%
\_file})$;\6
\4\&{const} \37\X21:Constants\X\6
\4\&{type} \37\X5:Types\X\6
\4\&{var} \37\X6:Global Variables\X\6
\4\&{procedure}\1\  \37\\{initialize};\2\6
\&{begin} \37\X11:Open input and output files\X\6
$\\{print\_ln}(\\{banner})$;\6
$\\{end\_of\_chr}\K\\{chr}(12)$;\6
\&{end};\par
\fi

\M3. Here are some macros for common programming idioms.

\Y\P\D \37$\\{incr}(\#)\S\#\K\#+1$\C{increase a variable by unity}\par
\P\D \37$\\{decr}(\#)\S\#\K\#-1$\C{decrease a variable by unity}\par
\P\D \37$\\{do\_nothing}\S$\C{empty statement}\par
\P\D \37$\\{shift}(\#)\S\#\K\#\ast2$\C{multiply by 2}\par
\P\D \37$\\{shift\_and\_add}(\#)\S\#\K\#\ast2+1$\C{multiply by 2 and add one}%
\par
\fi

\N4.  Font metric data.
The \.{CHR} file is in a format which allows it to be edited with a text
editor.  Once it has been edited, it needs to be converted back
into a \.{PXL} file which contains information that the \TeX\ typesetting
routines can use.  These \.{PXL} files store the information needed by
\TeX\ in a more compact way.

The character raster in the \.{CHR} file sits in an almost invisible bounding
box. This box is \\{almost} invisible in that all of the positions in the box
are represented by blank spaces, except for the position of the \\{x\_offset},
the
\\{y\_offset}, and the \\{origin}. These three positions are represented
respectively
by a dash (-), a bar (?), and a plus sign (+). The character raster sits at
the lower right corner of the bounding box, which means that there may be
space above or to the left of the raster, but not to the right or below it.
None of the dimensions in the following information include the bounding box,
but
instead refer only to the inside box containing the character raster.

If after editing the height or width changes, the \.{CHtoPX}
program will detect this and change the values before writing the new
\.{PXL} file.

A \.{CHR} file contains:\par
Font file information (see the \.{PXtoCH} documentation for more details
of these fields):
\yskip\hang \\{total\_char}:total number of characters\par
\hang \\{checksum} :matches the checksum in any \.{DVI} file that refers to
this font.\par
\hang \\{magnification} : 1000 times the magnification factor at which this
font was produced.\par
\hang \\{design\_size} : matches the design size in the
\.{TFM} file.\par
\hang \\{directory\_pointer} : pointer to the directory information. \par
\hang \\{pixel\_id} : currently $= 1001$ decimal.\par
\hang \\{max\_height}: not currently used, but available. The height of the
tallest
raster in the file.\par
\hang \\{max\_width}: also not used. The width of the widest raster in the
file.\par
\yskip\noindent

Character information:
\yskip\hang \\{chr\_code}:ascii code of the character in octal.\par
\hang \\{height} (*)(+): total height of the raster\par
\hang \\{width} (*)(+): total width of the raster\par
\hang \\{x\_offset} (*): offset from upper left hand corner of bounding box\par
\hang \\{y\_offset} (*): offset from upper left hand corner of bounding box\par
\hang \\{tfm\_width} (*): width that the \.{TFM} file thinks the character is
in \.{FIX}es\par
\yskip\noindent

Raster information:
\yskip\hang + - origin (-1,-1)\par
\hang - - x-offset\par
\hang : - y-offset\par
\hang . - white pixels in the raster\par
\hang * - black pixels in the raster\par
\yskip\noindent

\hbox {Sample raster: \hskip 1in

\vtop{\tt
\hbox {+   -             \hfill}
\hbox { .......*........ \hfill}
\hbox { ......*.*....... \hfill}
\hbox { .....*...*...... \hfill}
\hbox { ....*.....*..... \hfill}
\hbox {:...*********.... \hfill}
\hbox { .......*........ \hfill}
\hbox { .......*........ \hfill}
\hbox { .......*........ \hfill}
}}
\fi

\M5. \P$\X5:Types\X\S$\6
$\\{font\_rec}=$\1\5
\1\&{record} \37\\{pxl\_height}: \37\\{integer};\6
\4\\{pxl\_width}: \37\\{integer};\6
\4\\{x\_offset}: \37\\{integer};\6
\4\\{y\_offset}: \37\\{integer};\6
\4\\{raster\_addr}: \37\\{integer};\6
\4\\{tfm\_width}: \37\\{integer};\6
\4\\{chr\_code}: \37\\{integer};\2\6
\&{end};\2\6
$\\{font\_tbl\_type}=$\1\5
\&{packed} \37\&{array} $[1\to\\{tbl\_size}]$ \1\&{of}\5
\\{font\_rec};\2\2\par
\A sections~9 and~22.
\U section~2.\fi

\M6. \P$\X6:Global Variables\X\S$\6
\4\\{end\_of\_chr}: \37\\{char};\C{end of character marker}\6
\4\\{font\_info}: \37\\{font\_tbl\_type};\6
\4\\{save\_right}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_left}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_depth}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_internal\_width}: \37\\{integer};\C{value read in from \\{chr%
\_file}}\6
\4\\{old\_raster\_addr}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_kerning}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_top}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_bottom}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{save\_data\_row\_count}: \37\\{integer};\C{value read in from \\{chr%
\_file}}\6
\4\\{save\_raster\_width}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4$\\{total\_char},\39\\{checksum},\39\\{magnification},\39\\{design\_size},\39%
\\{directory\_ptr},\39\\{pixel\_id},\39\\{max\_height},\39\\{max\_width}$: \37%
\\{integer};\par
\A sections~7, 8, 10, 16, 23, 29, 33, 39, and~45.
\U section~2.\fi

\M7. Suffice it to say that a \.{CHR} file is an ordinary text file.
The \.{CHR} format is almost self-explanatory when you see an
example or two.

\Y\P$\4\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{chr\_file}: \37\\{text};\6
\4\\{page\_marker}: \37\\{char};\6
\4\\{file\_ok}: \37\\{boolean};\par
\fi

\M8. Additionally, an error file is provided which contains all error messages
for each character. This file can be specified to be the terminal, in which
case all the error messages will be displayed when the program is run.

\Y\P$\4\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{error\_file}: \37\\{text};\par
\fi

\M9. Detailed information about the \\{pxl\_file} appears in the documentation
of the companion program, \.{PXtoCH}, so it will not be repeated here.

\Y\P$\4\X5:Types\X\mathrel{+}\S$\6
$\\{byte}=0\to255$;\par
\fi

\M10. \P$\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{pxl\_file}: \37\&{packed} \37\&{file} \1\&{of}\5
\\{byte};\2\par
\fi

\M11. On some systems you may have to do something special to read a
packed file of bytes. For example, the following code didn't work
when it was first tried at Stanford, because packed files have to be
opened with a special switch setting on the \PASCAL\ that was used.

\Y\P$\4\X11:Open input and output files\X\S$\6
$\\{rewrite}(\\{pxl\_file})$;\6
$\\{reset}(\\{chr\_file})$;\6
$\\{rewrite}(\\{error\_file})$;\par
\U section~2.\fi

\M12. The input may, of course, be all screwed up and not a \.{CHR} file
at all, so we provide a means of escape.

\Y\P\D \37$\\{abort}(\#)\S$\1\6
\&{begin} \37$\\{print\_ln}(\#)$;\5
$\\{print\_ln}(\.{\'Sorry,\ but\ I\ can\'}\.{\'t\ go\ on.\ Are\ you\ sure\ this%
\ is\ a\ CHR\ file?\'})$;\6
$\\{file\_ok}\K\\{false}$;\6
\&{end}\2\par
\P\D \37$\\{error}(\#)\S\\{print\_ln}(\#)$\par
\fi

\N13.  Useful subroutines.
\fi

\M14. \\{Max} returns the larger of two integers.

\Y\P\4\&{function}\1\  \37$\\{max}(\|m,\39\|n:\\{integer})$: \37\\{integer};\2\6
\&{begin} \37\&{if} $\|m>\|n$ \1\&{then}\5
$\\{max}\K\|m$\6
\4\&{else} $\\{max}\K\|n$;\2\6
\&{end};\par
\fi

\M15. \\{Min} returns the smaller of two integers.

\Y\P\4\&{function}\1\  \37$\\{min}(\|m,\39\|n:\\{integer})$: \37\\{integer};\2\6
\&{begin} \37\&{if} $\|m>\|n$ \1\&{then}\5
$\\{min}\K\|n$\6
\4\&{else} $\\{min}\K\|m$;\2\6
\&{end};\par
\fi

\M16. If we are not at the end of the row, read the next character from
\\{chr\_file}. If we are at the end of the row, set \\{ch} to a predefined
\\{end\_of\_line} character.  If this is the end of the character (and also
the end of the page), set an \\{end\_of\_page} flag. If the character read in
matches the \\{end\_of\_line} character, it is an error, so change it to a
period and print out a message.

\Y\P$\4\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{end\_of\_page}: \37\\{boolean};\C{end of page flag}\6
\4\\{raster\_found}: \37\\{boolean};\C{end of raster flag}\6
\4\\{ch}: \37\\{char};\C{next character read in}\par
\fi

\M17. \P\6
\4\&{procedure}\1\  \37$\\{get\_next\_ch}(\mathop{\&{var}}\\{ch}:\\{char})$;\2\6
\&{begin} \37$\\{ch}\K\\{end\_of\_line}$;\6
\&{if} $\R\\{eoln}(\\{chr\_file})$ \1\&{then}\5
$\\{read}(\\{chr\_file},\39\\{ch})$;\2\6
\&{if} $\\{ch}=\\{end\_of\_chr}$ \1\&{then}\6
\&{begin} \37$\\{end\_of\_page}\K\\{true}$;\6
$\\{ch}\K\\{end\_of\_line}$;\6
\&{end}\2\6
\&{end};\par
\fi

\M18. If the header information is missing for a character, or the raster
image is too messed up to continue processing this character, then we will
skip it.  \\{Skip\_to\_next\_page} prints an error message, then skips to the
beginning of the next character in the file. Usually, each character
appears on a separate page.

\Y\P\4\&{procedure}\1\  \37\\{skip\_to\_next\_pg};\6
\4\&{var} \37\\{ch}: \37\\{char};\2\6
\&{begin} \37\1\&{repeat} \37$\\{read}(\\{chr\_file},\39\\{ch})$;\6
\4\&{until}\5
$(\\{ch}=\\{end\_of\_chr})\V\\{eof}(\\{chr\_file})$;\2\6
\&{if} $\\{eof}(\\{chr\_file})$ \1\&{then}\5
$\\{print\_ln}(\.{\'End\ of\ file.\'})$;\2\6
\&{end};\par
\fi

\M19. We want to write out the information to the \.{PXL} file in 8-bit bytes.
Here we convert a 32 bit number into 4 eight-bit bytes and write them out
in Big Endian order (highest byte first).

\Y\P\4\&{procedure}\1\  \37$\\{write\_pxl}(\\{oneword}:\\{integer})$;\6
\4\&{var} \37$\|k,\39\|l,\39\|m,\39\|n$: \37\\{byte};\2\6
\&{begin} \37$\|k\K\\{oneword}\mathbin{\&{div}}\O{100000000}$;\6
$\|l\K(\\{oneword}\mathbin{\&{div}}\O{200000})\mathbin{\&{mod}}256$;\6
$\|m\K(\\{oneword}\mathbin{\&{div}}256)\mathbin{\&{mod}}256$;\6
$\|n\K\\{oneword}\mathbin{\&{mod}}256$;\5
$\\{write}(\\{pxl\_file},\39\|k,\39\|l,\39\|m,\39\|n)$;\6
\&{end};\par
\fi

\M20. Here we convert a 16 bit number into 2 eight-bit bytes and write them out
in Big Endian order (highest byte first).

\Y\P\4\&{procedure}\1\  \37$\\{write\_half\_pxl}(\\{oneword}:\\{integer})$;\6
\4\&{var} \37$\|m,\39\|n$: \37\\{byte};\2\6
\&{begin} \37\&{if} $\\{oneword}<0$ \1\&{then}\5
$\\{oneword}\K(\\{oneword}+65536)$;\2\6
$\|m\K(\\{oneword}\mathbin{\&{div}}256)$;\6
$\|n\K(\\{oneword}\mathbin{\&{mod}}256)$;\5
$\\{write}(\\{pxl\_file},\39\|m,\39\|n)$;\6
\&{end};\par
\fi

\N21.  Read font information from CHR file.
The first step in processing the \.{CHR} file is to read in the font file
information. Certain fields must be found or the processing can't continue.
These fields originally came from the \.{PXL} file, and should not be
modified in any way if the \.{CHR} file is changed. They include:
\\{checksum}, \\{magnification}, \\{design\_size}, and \\{pixel\_id}. The other
fields
will be checked by \.{CHtoPX}, and if they don't match the current information
in the file, will be updated when the new \.{PXL} file is written out.
\\{Found\_info} is a flag indicating whether a particular field was found,
and \\{found\_all} keeps track of whether the necessary fields were found.
\\{File\_ok} checks to see if any information was found at all.

First we declare the constants, types and global variables we will need.
There is nothing special about the length of \\{info\_size}; sixteen was
chosen simply because all of the information needed fit into that length.

\Y\P$\4\X21:Constants\X\S$\6
$\\{info\_size}=16$;\6
$\\{screen\_width}=14$;\C{max. no of char that will fit on one screen / 6 }\par
\A section~32.
\U section~2.\fi

\M22. \P$\X5:Types\X\mathrel{+}\S$\6
$\\{infotype}=$\1\5
\&{packed} \37\&{array} $[1\to\\{info\_size}]$ \1\&{of}\5
\\{char};\2\2\par
\fi

\M23. \P$\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{info}: \37\\{infotype};\C{header we're looking for}\6
\4$\\{found\_info},\39\\{found\_all},\39\\{done}$: \37\\{boolean};\C{flags to
indicate what we've found}\6
\4\\{num}: \37\\{integer};\C{numeric value associated with the current header}\6
\4$\|i,\39\|j$: \37\\{integer};\C{we always need these somewhere, we may as
well declare them here. Maybe the next generation will use sensible names like
x and y, sigh.}\par
\fi

\M24. \P$\X24:Read font info\X\S$\6
$\\{file\_ok}\K\\{false}$;\6
$\\{found\_all}\K\\{true}$;\6
$\\{found\_info}\K\\{true}$;\6
$\\{read\_hdr}(\.{\'Font\ file\ info\ :\'},\39\\{found\_info})$;\6
$\\{read\_info}(\.{\'Number\ of\ char\ :\'},\39\\{total\_char},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{read\_info}(\.{\'Checksum\ \ \ \ \ \ \ :\'},\39\\{checksum},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{found\_all}\K\\{found\_all}\W\\{found\_info}$;\6
$\\{read\_info}(\.{\'Magnification\ \ :\'},\39\\{magnification},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{found\_all}\K\\{found\_all}\W\\{found\_info}$;\6
$\\{read\_info}(\.{\'Design\ size\ \ \ \ :\'},\39\\{design\_size},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{found\_all}\K\\{found\_all}\W\\{found\_info}$;\6
$\\{read\_info}(\.{\'Directory\ ptr\ \ :\'},\39\\{directory\_ptr},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{found\_all}\K\\{found\_all}\W\\{found\_info}$;\6
$\\{read\_info}(\.{\'Pixel\ Id\ \ \ \ \ \ \ :\'},\39\\{pixel\_id},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{found\_all}\K\\{found\_all}\W\\{found\_info}$;\6
$\\{read\_info}(\.{\'Max\ height\ \ \ \ \ :\'},\39\\{max\_height},\39\\{found%
\_info},\39\\{file\_ok})$;\6
$\\{read\_info}(\.{\'Max\ width\ \ \ \ \ \ :\'},\39\\{max\_width},\39\\{found%
\_info},\39\\{file\_ok})$;\6
\X25:Can we continue?\X\par
\U section~52.\fi

\M25. Check to see if the needed information was found, and whether we can
continue.
If everything was ok, write out the \\{pixel\_id} to the \\{pxl\_file}.

\Y\P$\4\X25:Can we continue?\X\S$\6
\&{if} $\R\\{file\_ok}$ \1\&{then}\5
$\\{abort}(\.{\'No\ font\ header\ information\ found.\'})$\6
\4\&{else} \&{if} $\R\\{found\_all}$ \1\&{then}\5
$\\{abort}(\.{\'Font\ header\ fields\ missing.\'})$\6
\4\&{else} \&{begin} \37$\\{write\_pxl}(\\{pixel\_id})$;\6
\\{skip\_to\_next\_pg};\6
\&{end};\2\2\par
\U section~24.\fi

\M26. This procedure reads in the header information and the value of the
field associated with the header. If the header information does not match
the expected header, a switch is set so that the next time this procedure
is called, the same field will be checked and no new one read in.  This
will work fine if there are lines missing; it will not work if there is an
extra line or the lines are out of order. If the value is missing, zero is
assumed.

\Y\P\4\&{procedure}\1\  \37$\\{read\_info}(\\{info}:\\{infotype};\,\35\mathop{%
\&{var}}\\{val}:\\{integer};\,\35\mathop{\&{var}}\\{found\_info}:\\{boolean};\,%
\35\mathop{\&{var}}\\{ok}:\\{boolean})$;\6
\4\&{var} \37\|i: \37\\{integer};\5
\\{name}: \37\\{infotype};\C{header we're reading in}\2\6
\&{begin} \37\&{if} $\\{found\_info}$ \1\&{then}\6
\&{begin} \37\&{for} $\|i\K1\mathrel{\&{to}}\\{info\_size}$ \1\&{do}\6
\&{if} $\R\\{eoln}(\\{chr\_file})$ \1\&{then}\5
$\\{read}(\\{chr\_file},\39\\{name}[\|i])$\6
\4\&{else} $\\{name}[\|i]\K\\{blank}$;\2\2\6
\&{if} $\R\\{eoln}(\\{chr\_file})$ \1\&{then}\5
$\\{readln}(\\{chr\_file},\39\\{num})$\6
\4\&{else} $\\{num}\K0$;\2\6
\&{end};\2\6
$\\{found\_info}\K\\{name}=\\{info}$;\6
$\\{ok}\K\\{found\_info}\V\\{ok}$;\6
\&{if} $\R\\{found\_info}$ \1\&{then}\5
$\\{val}\K0$\6
\4\&{else} $\\{val}\K\\{num}$;\2\6
\&{end};\par
\fi

\M27. This procedure reads in the file header. If
the header is missing, that's ok, but we'll print out an error message
anyway. We also set \\{found} to false, and just in case this is really the
next header, we will try to read in
a number following the header, and save it for the next go round.


\Y\P\4\&{procedure}\1\  \37$\\{read\_hdr}(\\{info}:\\{infotype};\,\35\mathop{%
\&{var}}\\{found\_info}:\\{boolean})$;\6
\4\&{var} \37\|i: \37\\{integer};\5
\\{name}: \37\\{infotype};\C{header we're reading in}\2\6
\&{begin} \37\&{for} $\|i\K1\mathrel{\&{to}}\\{info\_size}$ \1\&{do}\6
\&{if} $\R\\{eoln}(\\{chr\_file})$ \1\&{then}\5
$\\{read}(\\{chr\_file},\39\\{name}[\|i])$\6
\4\&{else} $\\{name}[\|i]\K\\{blank}$;\2\2\6
\&{if} $\\{name}\I\\{info}$ \1\&{then}\6
\&{begin} \37$\\{error}(\.{\'Font\ file\ header\ missing.\ Is\ this\ really\ a\
CHR\ file?\'})$;\5
$\\{error}(\.{\'I\ will\ try\ to\ continue\ anyway.\'})$;\5
$\\{found\_info}\K\\{false}$;\6
\&{if} $\R\\{eoln}(\\{chr\_file})$ \1\&{then}\5
$\\{read}(\\{chr\_file},\39\\{num})$\6
\4\&{else} $\\{num}\K0$;\2\6
\&{end};\2\6
$\\{readln}(\\{chr\_file})$;\6
\&{end};\par
\fi

\N28.  Read character header.
Now, for each character, the character header is read in, then if the
header is ok, the character raster is read, converted to binary, and
written out. The information about the character is saved in \\{font\_info}.
If the header information is missing the character is skipped.

\Y\P$\4\X28:Read and save character information\X\S$\6
\X30:Read character header\X\6
\&{if} $\R\\{chr\_ok}$ \1\&{then}\6
\&{begin} \37$\\{error}(\.{\'No\ character\ header\ information\ found.\'})$;\6
\\{skip\_to\_next\_pg};\6
\&{end}\6
\4\&{else} \X34:Read character raster\X\2\par
\U section~50.\fi

\M29. \P$\X6:Global Variables\X\mathrel{+}\S$\6
\4$\\{chr\_index},\39\\{temp\_chr}$: \37\\{integer};\6
\4\\{chr\_code}: \37\\{integer};\C{value read in from \\{chr\_file}}\6
\4\\{chr\_ok}: \37\\{boolean};\6
\4\\{chr\_count}: \37\\{integer};\C{keeps track of whether we need to start a
new line}\par
\fi

\M30. Read in the character information using the same procedure as was used
for
the font information header. Note again, this will work if there are headers
missing, but not if they are out of order or there are extra headers.

The only field that is required in the header is the \\{chr\_code}, because
without it, we have no idea what character we are processing!  If the
\\{chr\_code} is missing, we will skip this character and go on to the next.
Note that the \\{chr\_code} must be the first line of the header, or we
assume that it isn't there.  The other fields will be checked by
\.{CHtoPX}, and if they don't match the current information in the file,
then will be updated when the new \.{PXL} file is written out.
If no value can be calculated, such as for \\{tfm\_width}, it will be set to
zero.
\\{Found\_info} isλa flag indicating whether a particular field was found,
and \\{chr\_ok} checks to see if any information was found at all.

\Y\P$\4\X30:Read character header\X\S$\6
$\\{chr\_ok}\K\\{false}$;\6
$\\{found\_info}\K\\{true}$;\6
$\\{read\_info}(\.{\'chrcode\ \ \ \ \ \ \ \ :\'},\39\\{chr\_code},\39\\{found%
\_info},\39\\{chr\_ok})$;\6
\&{if} $\\{found\_info}$ \1\&{then}\6
\&{begin} \37$\\{print}(\.{\'[\'},\39\\{chr\_code}:1,\39\.{\']\'})$;\6
$\\{incr}(\\{chr\_count})$;\6
\&{if} $\\{chr\_count}>\\{screen\_width}$ \1\&{then}\6
\&{begin} \37$\\{print\_ln}(\.{\'\ \'})$;\6
$\\{chr\_count}\K0$;\6
\&{end};\2\6
\X31:Convert \\{chr\_code} into decimal\X\6
$\\{read\_info}(\.{\'height\ \ \ \ \ \ \ \ \ :\'},\39\\{font\_info}[\\{chr%
\_index}].\\{pxl\_height},\39\\{found\_info},\39\\{chr\_ok})$;\5
$\\{read\_info}(\.{\'width\ \ \ \ \ \ \ \ \ \ :\'},\39\\{font\_info}[\\{chr%
\_index}].\\{pxl\_width},\39\\{found\_info},\39\\{chr\_ok})$;\5
$\\{read\_info}(\.{\'x\ offset\ \ \ \ \ \ \ :\'},\39\\{font\_info}[\\{chr%
\_index}].\\{x\_offset},\39\\{found\_info},\39\\{chr\_ok})$;\5
$\\{read\_info}(\.{\'y\ offset\ \ \ \ \ \ \ :\'},\39\\{font\_info}[\\{chr%
\_index}].\\{y\_offset},\39\\{found\_info},\39\\{chr\_ok})$;\5
$\\{read\_info}(\.{\'tfm\ width\ \ \ \ \ \ :\'},\39\\{font\_info}[\\{chr%
\_index}].\\{tfm\_width},\39\\{found\_info},\39\\{chr\_ok})$;\6
\&{end}\6
\4\&{else} $\\{error}(\.{\'Didn\'}\.{\'t\ find\ chr\_code.\'})$;\2\par
\U section~28.\fi

\M31. \P$\X31:Convert \\{chr\_code} into decimal\X\S$\6
$\\{chr\_index}\K(\\{chr\_code}\mathbin{\&{div}}100)\ast64$;\6
$\\{temp\_chr}\K\\{chr\_code}\mathbin{\&{mod}}100$;\6
$\\{chr\_index}\K\\{chr\_index}+(\\{temp\_chr}\mathbin{\&{div}}10)\ast8$;\6
$\\{temp\_chr}\K\\{temp\_chr}\mathbin{\&{mod}}10$;\6
$\\{chr\_index}\K\\{chr\_index}+\\{temp\_chr}+1$;\5
$\\{font\_info}[\\{chr\_index}].\\{chr\_code}\K\\{chr\_code}$;\par
\U section~30.\fi

\N32.  Find raster image.
The character raster sits inside a bounding box which contains information
about
the position of the character within the raster. This outside box may contain
any number of rows or columns above or to the left of the character, any or all
of
which may be blank (but hopefully not, since we are looking for something in
these
rows and columns). Our first
task, therefore, is to find out where the raster is inside this box, and at
the same time, to save any information the outside box contains pertaining to
the
\\{x\_offset}(indicated by a dash), the \\{y\_offset}(a colon), or the
\\{origin}(a plus) of the raster.

\Y\P$\4\X21:Constants\X\mathrel{+}\S$\6
$\\{tbl\_size}=128$;\C{current maximum number of characters allowed in file}\6
$\\{asterisk}=\.{\'*\'}$;\C{represents a pixel that is `on', or black}\6
$\\{blank}=\.{\'\ \'}$;\C{filler for bounding box}\6
$\\{period}=\.{\'.\'}$;\C{represents a pixel that is `off', or white}\6
$\\{plus}=\.{\'+\'}$;\C{the (0,0) position in the raster}\6
$\\{dash}=\.{\'-\'}$;\C{the \\{x\_offset}}\6
$\\{bar}=\.{\':\'}$;\C{the \\{y\_offset}}\6
$\\{end\_of\_line}=\.{\'!\'}$;\C{marker to signal when we've reached the end of
a line}\par
\fi

\M33. \P$\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{found}: \37$(\\{both},\39\\{origin},\39\\{x\_off},\39\\{none},\39%
\\{letter})$;\C{state information, what have we found?}\6
\4\\{raster\_addr}: \37\\{integer};\C{keeps track of how many words have been
written on the \\{pxl\_file}}\6
\4\\{x\_offset}: \37\\{integer};\C{position of \\{x\_offset}}\6
\4\\{y\_offset}: \37\\{integer};\C{position of \\{y\_offset}}\6
\4\\{first\_column}: \37\\{integer};\C{position of the first column of the
character raster}\6
\4\\{bar\_row}: \37\\{integer};\C{row where we found the bar}\6
\4\\{col\_index}: \37\\{integer};\C{current column}\6
\4\\{row\_index}: \37\\{integer};\C{current row}\6
\4\\{dash\_column}: \37\\{integer};\C{column where dash found}\6
\4\\{plus\_column}: \37\\{integer};\C{column where plus found}\6
\4\\{plus\_row}: \37\\{integer};\C{row where plus found}\par
\fi

\M34. It is here that things get sticky. There is no knowing whether either the
offset information or the raster itself
has been modified since being created by
\.{PXtoCH}, and there could be all sorts of strange data in it. We will
hope for the best, yet proceed with caution.

\Y\P$\4\X34:Read character raster\X\S$\6
\&{begin} \37$\\{end\_of\_page}\K\\{false}$;\6
$\\{row\_index}\K0$;\6
$\\{col\_index}\K0$;\6
$\\{found}\K\\{none}$;\6
\X36:Skip to beginning of character\X\6
\&{if} $\\{end\_of\_page}$ \1\&{then}\6
\&{begin} \37$\\{error}(\.{\'No\ raster\ found.\'})$;\6
\X35:Zero all fields\X\6
\&{end}\6
\4\&{else} \&{begin} \37\X40:Process raster\X\6
\X46:Compare old with new values\X\6
\&{end};\2\6
\&{end};\par
\U section~28.\fi

\M35. If no raster information was found, no character information will be
saved,
so all the fields for that character are zeroed out in the \\{font\_info}.

\Y\P$\4\X35:Zero all fields\X\S$\6
$\\{font\_info}[\\{chr\_index}].\\{pxl\_height}\K0$;\6
$\\{font\_info}[\\{chr\_index}].\\{pxl\_width}\K0$;\6
$\\{font\_info}[\\{chr\_index}].\\{x\_offset}\K0$;\6
$\\{font\_info}[\\{chr\_index}].\\{y\_offset}\K0$;\6
$\\{font\_info}[\\{chr\_index}].\\{raster\_addr}\K0$;\6
$\\{font\_info}[\\{chr\_index}].\\{tfm\_width}\K0$;\par
\U section~34.\fi

\M36. Search for the raster.
Read \\{chr\_file} until we reach the first period or asterisk, signalling the
beginning of the character itself. Look for
a plus, dash, or colon, which will indicate the position of the origin,
x-offset,
and y-offset, respectively. If no period or asterisk is found, the character
doesn't exist, and no information will be written out to the \\{pxl\_file}.

\Y\P$\4\X36:Skip to beginning of character\X\S$\6
$\\{dash\_column}\K-1$;\6
$\\{plus\_column}\K-1$;\6
$\\{plus\_row}\K-1$;\6
$\\{bar\_row}\K-1$;\6
$\\{x\_offset}\K-1$;\6
$\\{y\_offset}\K-1$;\6
$\\{first\_column}\K-1$;\6
\1\&{repeat} \37$\\{get\_next\_ch}(\\{ch})$;\6
\X37:What is it?\X\6
$\\{incr}(\\{col\_index})$;\6
\4\&{until}\5
$(\\{end\_of\_page})\V(\\{found}=\\{letter})$;\2\par
\U section~34.\fi

\M37. After we read in the next character, check it to see what it is. If it
is a \\{plus}, it is the origin; if a \\{dash}, it is the x-offset; if it is a %
\\{bar},
it is the y-offset; if it is a \\{blank}, it is a place holder; if it is a
\\{period} or \\{asterisk}, it is the beginning of the character raster.
At the \\{end\_of\_line} we increment the row count and reset the column count.
\Y\P$\4\X37:What is it?\X\S$\6
\&{case} $\\{ch}$ \1\&{of}\6
\4\\{plus}: \37\&{begin} \37\&{if} $(\\{found}=\\{origin})\V(\\{found}=%
\\{both})$ \1\&{then}\5
$\\{error}(\.{\'duplicate\ origin\ (+)\ found\'})$\6
\4\&{else} \&{begin} \37\&{if} $\\{found}=\\{x\_off}$ \1\&{then}\5
$\\{found}\K\\{both}$\6
\4\&{else} $\\{found}\K\\{origin}$;\2\6
$\\{plus\_column}\K\\{col\_index}$;\6
$\\{plus\_row}\K\\{row\_index}$;\6
\&{end};\2\6
\&{end};\6
\4\\{dash}: \37\&{begin} \37\&{if} $(\\{found}=\\{x\_off})\V(\\{found}=%
\\{both})$ \1\&{then}\5
$\\{error}(\.{\'duplicate\ x\ offset\ (-)\ found.\'})$\6
\4\&{else} \&{begin} \37\&{if} $\\{found}=\\{origin}$ \1\&{then}\5
$\\{found}\K\\{both}$\6
\4\&{else} $\\{found}\K\\{x\_off}$;\2\6
$\\{dash\_column}\K\\{col\_index}$;\6
\&{end};\2\6
\&{end};\6
\4\\{bar}: \37$\\{bar\_row}\K\\{row\_index}$;\6
\4\\{blank}: \37\\{do\_nothing};\6
\4$\\{asterisk},\39\\{period}$: \37\X38:Save offset information\X;\6
\4\\{end\_of\_line}: \37\&{begin} \37$\\{readln}(\\{chr\_file})$;\6
$\\{incr}(\\{row\_index})$;\6
$\\{col\_index}\K-1$;\6
\&{end};\2\6
\&{end};\par
\U section~36.\fi

\M38. When we find the first period or asterisk, check to see what state we
are in.  If we have found the x-offset (dash) or y-offset (colon), save
their position, relative to the origin. If the x-offset or origin wasn't
found, assume that they are both zero. If the y-offset wasn't found,
that's ok, since it could be that we just haven't gotten to it yet.
There will be some number of spaces to the left of the raster (minimum of one)
and we will save this number in \\{first\_column}, so that when we start to
process
the raster image, we know how many spaces to skip before beginning processing.

\Y\P$\4\X38:Save offset information\X\S$\6
\&{begin} \37\&{case} $\\{found}$ \1\&{of}\6
\4$\\{both},\39\\{letter}$: \37\\{do\_nothing};\6
\4\\{origin}: \37$\\{dash\_column}\K\\{plus\_column}$;\6
\4\\{x\_off}: \37$\\{error}(\.{\'origin\ (+)\ not\ found.\ Substituting\ 0.%
\'})$;\6
\4\\{none}: \37$\\{error}(\.{\'origin(+)\ and\ x\ offset\ (-)\ not\ found.\
Using\ 0\ for\ both.\'})$;\2\6
\&{end};\6
$\\{first\_column}\K\\{col\_index}$;\6
$\\{found}\K\\{letter}$;\6
$\\{x\_offset}\K\\{dash\_column}-\\{plus\_column}-1$;\6
$\\{y\_offset}\K\\{bar\_row}-\\{plus\_row}-1$;\6
\&{end}\par
\U section~37.\fi

\N39.  Read character raster.
Here we read in each row of the character, and convert it
into an equivalent binary number. This number must have four bytes of eight
bits for a total of 32 positions, so if the row we are reading in does
not have a multiple of 32 positions, we have to fill it with zeros so that it
does.
Each 8 bit number is then written out to the \\{pxl\_file}. This process is
repeated
for each row in the character. Hopefully, each row will have the same number
of characters in it; if they don't, then the raster is not rectangular,
which could indicate a problem. The raster is processed as is, but a warning
message is printed out. The character raster is read until either an
\\{end\_of\_page} marker or a blank line is found.

\Y\P\D \37$\\{out}(\#)\S\\{write}(\\{pxl\_file},\39(\#\mathbin{\&{mod}}256))$;%
\par
\Y\P$\4\X6:Global Variables\X\mathrel{+}\S$\6
\4$\\{row},\39\\{save\_byte},\39\\{left},\39\\{right},\39\\{top},\39\\{bottom},%
\39\\{num\_words}$: \37\\{integer};\6
\4\\{bit}: \37\\{integer};\6
\4\\{first\_line}: \37\\{boolean};\C{is this the first row of the raster?}\6
\4\\{last\_col}: \37\\{boolean};\C{is this the last col of the raster?}\6
\4\\{top\_found}: \37\\{boolean};\C{have we found the first asterisk?}\6
\4\\{line\_width}: \37\\{integer};\par
\fi

\M40. \P$\X40:Process raster\X\S$\6
$\\{top\_found}\K\\{false}$;\6
$\\{left}\K\\{max\_width}$;\6
$\\{right}\K0$;\6
$\\{top}\K0$;\6
$\\{bottom}\K0$;\6
$\\{old\_raster\_addr}\K\\{raster\_addr}$;\6
$\\{save\_byte}\K0$;\6
$\\{end\_of\_page}\K\\{false}$;\6
$\\{row}\K\\{row\_index}-1$;\6
$\\{line\_width}\K0$;\6
$\\{last\_col}\K\\{true}$;\6
$\\{first\_line}\K\\{true}$;\6
\1\&{repeat} \37$\\{num\_words}\K0$;\6
$\\{row}\K\\{row}+1$;\6
\1\&{repeat} \37$\\{incr}(\\{num\_words})$;\5
$\\{raster\_found}\K\\{false}$;\6
\&{for} $\|i\K1\mathrel{\&{to}}4$ \1\&{do}\C{4 bytes of}\6
\&{begin} \37\&{for} $\|j\K1\mathrel{\&{to}}8$ \1\&{do}\C{8 bits each}\6
\X41:Convert character raster\X\2\6
\&{if} $\\{raster\_found}$ \1\&{then}\6
\&{begin} \37$\\{out}(\\{save\_byte})$;\6
$\\{save\_byte}\K0$;\6
\&{end};\2\6
\&{end};\2\6
\&{if} $\\{raster\_found}$ \1\&{then}\5
$\\{incr}(\\{raster\_addr})$;\2\6
\4\&{until}\5
$\\{ch}=\\{end\_of\_line}$;\2\6
\&{if} $\R\\{end\_of\_page}\W\\{raster\_found}$ \1\&{then}\5
\X43:Find beginning of raster\X\2\6
\4\&{until}\5
$\\{end\_of\_page}\V\R\\{raster\_found}$;\2\6
\&{if} $\R\\{raster\_found}$ \1\&{then}\5
\\{skip\_to\_next\_pg};\2\par
\U section~34.\fi

\M41. Read the next character and convert it. If it is a period, it becomes a
zero; if it is an asterisk, it becomes a one; if it is anything else, it
is treated as a period. What we are doing here is converting the raster
made up of periods and asterisks into a binary number. This number will be
saved by writing it out to the \\{pxl\_file}. We are converting it bit by bit,
so for each character we read in, we either add a zero or a one onto the
end of the number we have calculated so far.

When we get to the end of the line, we also check to see if the line width
matches the width of the first line of the character. If it doesn't, then
the character raster is not rectangular, so an error message is printed, but
processing continues.

\Y\P$\4\X41:Convert character raster\X\S$\6
\&{begin} \37$\\{bit}\K(\|j+(\|i-1)\ast8)+(\\{num\_words}-1)\ast32$;\6
\&{case} $\\{ch}$ \1\&{of}\6
\4\\{asterisk}: \37\&{begin} \37$\\{shift\_and\_add}(\\{save\_byte})$;\6
$\\{raster\_found}\K\\{true}$;\5
\X42:Check extremes\X\6
\&{end};\6
\4\\{period}: \37\&{begin} \37$\\{shift}(\\{save\_byte})$;\6
$\\{raster\_found}\K\\{true}$;\5
\X42:Check extremes\X\6
\&{end};\6
\4\\{end\_of\_line}: \37\&{begin} \37$\\{shift}(\\{save\_byte})$;\6
\&{if} $\\{first\_line}$ \1\&{then}\6
\&{begin} \37$\\{first\_line}\K\\{false}$;\6
$\\{last\_col}\K\\{false}$;\6
$\\{line\_width}\K\\{bit}-1$;\6
\&{end}\6
\4\&{else} \&{if} $\\{last\_col}$ \1\&{then}\6
\&{begin} \37\&{if} $\\{bit}\I\\{line\_width}$ \1\&{then}\5
$\\{error}(\.{\'Character\ has\ uneven\ width.\ Processing\ as\ is.\'})$;\2\6
$\\{last\_col}\K\\{false}$;\6
\&{end};\2\2\6
\&{end};\6
\4\\{blank}: \37$\\{shift}(\\{save\_byte})$;\6
\4\\{others}: \37\&{begin} \37$\\{error}(\.{\'Unrecognized\ character.\
Assuming\ period.\'})$;\6
$\\{shift}(\\{save\_byte})$;\6
\&{end}\2\6
\&{end};\6
$\\{get\_next\_ch}(\\{ch})$;\6
\&{end};\par
\U section~40.\fi

\M42. We want to keep track of the size of the character within the raster,
so we can compare it to the values read in in the header. \\{Left}, \\{right},
\\{top}, and \\{bottom} will be used for comparison.
\Y\P$\4\X42:Check extremes\X\S$\6
$\\{left}\K\\{min}(\\{bit},\39\\{left})$;\6
$\\{right}\K\\{max}(\\{bit},\39\\{right})$;\6
\&{if} $\R\\{top\_found}$ \1\&{then}\6
\&{begin} \37$\\{top\_found}\K\\{true}$;\6
$\\{top}\K\\{row}$;\6
\&{end};\2\6
$\\{bottom}\K\\{row}$;\par
\U sections~41 and~41.\fi

\M43. Skip over the space to the left of the raster image which is part of the
outside box. If a colon is found, save the row number as the \\{y\_offset}.

\Y\P$\4\X43:Find beginning of raster\X\S$\6
\&{begin} \37$\\{readln}(\\{chr\_file})$;\6
\&{for} $\|i\K0\mathrel{\&{to}}\\{first\_column}$ \1\&{do}\6
\&{begin} \37$\\{get\_next\_ch}(\\{ch})$;\6
\&{if} $\\{ch}=\\{bar}$ \1\&{then}\5
$\\{y\_offset}\K\\{row}$;\2\6
\&{end};\2\6
\&{end};\par
\U section~40.\fi

\M44. Check to see if the two fields, \\{num1} and \\{num2}, match.  If not,
replace the second with the first and set a flag so we'll know a
replacement has been done.
\Y\P\4\&{procedure}\1\  \37$\\{check\_match}(\mathop{\&{var}}\\{num1}:%
\\{integer};\,\35\mathop{\&{var}}\\{num2}:\\{integer};\,\35\mathop{\&{var}}%
\\{flag}:\\{boolean})$;\2\6
\&{begin} \37\&{if} $\\{num1}\I\\{num2}$ \1\&{then}\5
$\\{flag}\K\\{false}$;\2\6
$\\{num2}\K\\{num1}$;\6
\&{end};\par
\fi

\M45. \P$\X6:Global Variables\X\mathrel{+}\S$\6
\4\\{width}: \37\\{integer};\C{width of the raster we just read in}\6
\4\\{height}: \37\\{integer};\C{height of the raster we just read in}\6
\4\\{all\_match}: \37\\{boolean};\C{used to see if everything matched the
values read in}\par
\fi

\M46. Check to see if the values read in really match the raster. If not, save
the
raster values and print an error message.
\Y\P$\4\X46:Compare old with new values\X\S$\6
$\\{all\_match}\K\\{true}$;\6
$\\{width}\K\\{right}-\\{left}+1$;\6
$\\{height}\K\\{bottom}-\\{top}+1$;\6
$\\{check\_match}(\\{width},\39\\{font\_info}[\\{chr\_index}].\\{pxl\_width},%
\39\\{all\_match})$;\6
$\\{check\_match}(\\{height},\39\\{font\_info}[\\{chr\_index}].\\{pxl\_height},%
\39\\{all\_match})$;\6
$\\{check\_match}(\\{x\_offset},\39\\{font\_info}[\\{chr\_index}].\\{x%
\_offset},\39\\{all\_match})$;\6
$\\{check\_match}(\\{y\_offset},\39\\{font\_info}[\\{chr\_index}].\\{y%
\_offset},\39\\{all\_match})$;\6
$\\{font\_info}[\\{chr\_index}].\\{raster\_addr}\K\\{old\_raster\_addr}$;\6
\&{if} $\R\\{all\_match}$ \1\&{then}\6
\&{begin} \37$\\{error}(\.{\'\'}\.{\'\'})$;\C{skip to next line}\6
$\\{error}(\.{\'Character\ raster\ does\ not\ match\ saved\ information.\'})$;\6
$\\{error}(\.{\'Correct\ information\ has\ been\ saved.\'})$;\6
\&{end}\2\par
\U section~34.\fi

\N47.  Write PXL file information.
First, write out all of the font directory information to the \\{pxl\_file}.

\Y\P$\4\X47:Write directory information to \.{PXL} file\X\S$\6
\&{for} $\|i\K1\mathrel{\&{to}}\\{tbl\_size}$ \1\&{do}\6
\&{begin} \37$\\{write\_half\_pxl}(\\{font\_info}[\|i].\\{pxl\_width})$;\6
$\\{write\_half\_pxl}(\\{font\_info}[\|i].\\{pxl\_height})$;\6
$\\{write\_half\_pxl}(\\{font\_info}[\|i].\\{x\_offset})$;\6
$\\{write\_half\_pxl}(\\{font\_info}[\|i].\\{y\_offset})$;\6
$\\{write\_pxl}(\\{font\_info}[\|i].\\{raster\_addr})$;\6
$\\{write\_pxl}(\\{font\_info}[\|i].\\{tfm\_width})$;\6
\&{end};\2\par
\U section~51.\fi

\M48. Finally, write out the font information to the \\{pxl\_file}, and we are
done.
\Y\P$\4\X48:Write font information to \.{PXL} file\X\S$\6
$\\{write\_pxl}(\\{checksum})$;\6
$\\{write\_pxl}(\\{magnification})$;\6
$\\{write\_pxl}(\\{design\_size})$;\6
$\\{all\_match}\K\\{true}$;\6
$\\{check\_match}(\\{raster\_addr},\39\\{directory\_ptr},\39\\{all\_match})$;\6
\&{if} $\R\\{all\_match}$ \1\&{then}\5
$\\{error}(\.{\'Saved\ new\ directory\ pointer.\'})$;\2\6
$\\{write\_pxl}(\\{directory\_ptr})$;\6
$\\{write\_pxl}(\\{pixel\_id})$;\6
$\\{print\_ln}(\.{\'All\ done.\'})$;\par
\U section~51.\fi

\N49.  Main program.
\fi

\M50. First read in the \.{CHR} file and process the characters.
\Y\P$\4\X50:Read \\{chr\_file}\X\S$\6
\1\&{repeat} \37\X28:Read and save character information\X\6
\4\&{until}\5
$\\{eof}(\\{chr\_file})$;\2\par
\U section~52.\fi

\M51. Then write out the \.{PXL} directory information and font information.
\Y\P$\4\X51:Write \\{pxl\_file}\X\S$\6
\X47:Write directory information to \.{PXL} file\X\6
\X48:Write font information to \.{PXL} file\X\par
\U section~52.\fi

\M52. Main program. Here's where we make it, or don't.

\Y\P\&{begin} \37\\{initialize};\6
\X24:Read font info\X\6
$\\{raster\_addr}\K1$;\6
$\\{chr\_count}\K0$;\6
\&{if} $\\{file\_ok}$ \1\&{then}\6
\&{begin} \37\X50:Read \\{chr\_file}\X\6
\X51:Write \\{pxl\_file}\X\6
\&{end};\2\6
\&{end}.\par
\fi

\N53.  System-dependent changes.
This module should be replaced, if necessary, by changes to the program
that are necessary to make \.{CHtoPX} work at a particular installation.
It is usually best to design your change file so that all changes to
previous modules preserve the module numbering; then everybody's version
will be consistent with the printed program. More extensive changes,
which introduce new modules, can be inserted here; then only the index
itself will get a new module number.




\fi

\N54.  Index.
Pointers to error messages appear here together with the section numbers
where each ident\-i\-fier is used.
\fi


\inx
\:\\{abort}, \[12], 25.
\:\\{all\_match}, \[45], 46, 48.
\:\\{almost}, 4.
\:\\{asterisk}, \[32], 37, 41.
\:\\{banner}, \[1], 2.
\:\\{bar}, \[32], 37, 43.
\:\\{bar\_row}, \[33], 36, 37, 38.
\:\\{bit}, \[39], 41, 42.
\:\\{blank}, 26, 27, \[32], 37, 41.
\:\\{boolean}, 7, 16, 23, 26, 27, 29, 39, 44, 45.
\:\\{both}, 33, 37, 38.
\:\\{bottom}, \[39], 40, 42, 46.
\:\\{byte}, \[9], 10, 19, 20.
\:\\{ch}, \[16], \[17], \[18], 36, 37, 40, 41, 43.
\:\\{char}, 6, 7, 16, 17, 18, 22.
\:\\{check\_match}, \[44], 46, 48.
\:\\{checksum}, 4, \[6], 21, 24, 48.
\:{Chinese characters}, 1.
\:\\{chr}, 2.
\:\\{chr\_code}, 4, \[5], \[29], 30, 31.
\:\\{chr\_count}, \[29], 30, 52.
\:\\{chr\_file}, \[2], 6, \[7], 11, 16, 17, 18, 26, 27, 29, 36, 37, 43, 50.
\:\\{chr\_index}, \[29], 30, 31, 35, 46.
\:\\{chr\_ok}, 28, \[29], 30.
\:\\{CHtoPX}, \[2].
\:\\{col\_index}, \[33], 34, 36, 37, 38.
\:\\{dash}, \[32], 37.
\:\\{dash\_column}, \[33], 36, 37, 38.
\:\\{decr}, \[3].
\:\\{design\_size}, 4, \[6], 21, 24, 48.
\:\\{directory\_pointer}, 4.
\:\\{directory\_ptr}, \[6], 24, 48.
\:\\{do\_nothing}, \[3], 37, 38.
\:\\{done}, \[23].
\:\\{end\_of\_chr}, 2, \[6], 17, 18.
\:\\{end\_of\_line}, 16, 17, \[32], 37, 40, 41.
\:\\{end\_of\_page}, \[16], 17, 34, 36, 39, 40.
\:\\{eof}, 18, 50.
\:\\{eoln}, 17, 26, 27.
\:\\{error}, \[12], 27, 28, 30, 34, 37, 38, 41, 46, 48.
\:\\{error\_file}, \[2], \[8], 11.
\:\\{false}, 12, 24, 27, 30, 34, 40, 41, 44.
\:\\{file\_ok}, \[7], 12, 24, 25, 52.
\:\\{File\_ok}, 21.
\:\\{first\_column}, \[33], 36, 38, 43.
\:\\{first\_line}, \[39], 40, 41.
\:\\{flag}, \[44].
\:\\{font\_info}, \[6], 28, 30, 31, 35, 46, 47.
\:\\{font\_rec}, \[5].
\:\\{font\_tbl\_type}, \[5], 6.
\:\\{found}, 27, \[33], 34, 36, 37, 38.
\:\\{found\_all}, 21, \[23], 24, 25.
\:\\{found\_info}, \[23], 24, \[26], \[27], 30.
\:\\{Found\_info}, 21, 30.
\:\\{get\_next\_ch}, \[17], 36, 41, 43.
\:\\{height}, 4, \[45], 46.
\:\|{i}, \[23], \[26], \[27].
\:\\{incr}, \[3], 30, 36, 37, 40.
\:\\{info}, \[23], 26, 27.
\:\\{info\_size}, \[21], 22, 26, 27.
\:\\{infotype}, \[22], 23, 26, 27.
\:\\{initialize}, \[2], 52.
\:\\{integer}, 5, 6, 14, 15, 19, 20, 23, 26, 27, 29, 33, 39, 44, 45.
\:\|{j}, \[23].
\:{Japanese characters}, 1.
\:\|{k}, \[19].
\:\\{last\_col}, \[39], 40, 41.
\:\\{Left}, 42.
\:\\{left}, \[39], 40, 42, 46.
\:\\{letter}, 33, 36, 38.
\:\\{line\_width}, \[39], 40, 41.
\:\|{m}, \[20].
\:\\{magnification}, 4, \[6], 21, 24, 48.
\:\\{max}, \[14], 42.
\:\\{Max}, 14.
\:\\{max\_height}, 4, \[6], 24.
\:\\{max\_width}, 4, \[6], 24, 40.
\:\\{min}, \[15], 42.
\:\\{Min}, 15.
\:\\{name}, \[26], \[27].
\:\\{none}, 33, 34, 38.
\:\\{num}, \[23], 26, 27.
\:\\{num\_words}, \[39], 40, 41.
\:\\{num1}, \[44].
\:\\{num2}, \[44].
\:\\{ok}, \[26].
\:\\{old\_raster\_addr}, \[6], 40, 46.
\:\\{oneword}, \[19], 20.
\:{oriental characters}, 1.
\:\\{origin}, 4, 32, 33, 37, 38.
\:\\{others}, 41.
\:\\{out}, \[39], 40.
\:\\{page\_marker}, 2, \[7].
\:\\{period}, \[32], 37, 41.
\:\\{pixel\_id}, 4, \[6], 21, 24, 25, 48.
\:\\{plus}, \[32], 37.
\:\\{plus\_column}, \[33], 36, 37, 38.
\:\\{plus\_row}, \[33], 36, 37, 38.
\:\\{print}, \[2], 30.
\:\\{print\_ln}, \[2], 12, 18, 30, 48.
\:\\{pxl\_file}, \[2], 9, \[10], 11, 19, 20, 25, 33, 36, 39, 41, 47, 48.
\:\\{pxl\_height}, \[5], 30, 35, 46, 47.
\:\\{pxl\_width}, \[5], 30, 35, 46, 47.
\:\\{raster\_addr}, \[5], \[33], 35, 40, 46, 47, 48, 52.
\:\\{raster\_found}, \[16], 40, 41.
\:\\{read}, 17, 18, 26, 27.
\:\\{read\_hdr}, 24, \[27].
\:\\{read\_info}, 24, \[26], 30.
\:\\{readln}, 26, 27, 37, 43.
\:\\{reset}, 11.
\:\\{rewrite}, 11.
\:\\{right}, \[39], 40, 42, 46.
\:\\{row}, \[39], 40, 42, 43.
\:\\{row\_index}, \[33], 34, 37, 40.
\:\\{save\_bottom}, \[6].
\:\\{save\_byte}, \[39], 40, 41.
\:\\{save\_data\_row\_count}, \[6].
\:\\{save\_depth}, \[6].
\:\\{save\_internal\_width}, \[6].
\:\\{save\_kerning}, \[6].
\:\\{save\_left}, \[6].
\:\\{save\_raster\_width}, \[6].
\:\\{save\_right}, \[6].
\:\\{save\_top}, \[6].
\:\\{screen\_width}, \[21], 30.
\:\\{shift}, \[3], 41.
\:\\{shift\_and\_add}, \[3], 41.
\:\\{Skip\_to\_next\_page}, 18.
\:\\{skip\_to\_next\_pg}, \[18], 25, 28, 40.
\:{system dependencies}, 2, 11, 53.
\:\\{tbl\_size}, 5, \[32], 47.
\:\\{temp\_chr}, \[29], 31.
\:\\{text}, 7, 8.
\:\\{tfm\_width}, 4, \[5], 30, 35, 47.
\:\\{top}, \[39], 40, 42, 46.
\:\\{top\_found}, \[39], 40, 42.
\:\\{total\_char}, 4, \[6], 24.
\:\\{true}, 17, 24, 30, 40, 41, 42, 46, 48.
\:\\{val}, \[26].
\:\\{width}, 4, \[45], 46.
\:\\{write}, 2, 19, 20, 39.
\:\\{write\_half\_pxl}, \[20], 47.
\:\\{write\_ln}, 2.
\:\\{write\_pxl}, \[19], 25, 47, 48.
\:\\{x\_off}, 33, 37, 38.
\:\\{x\_offset}, 4, \[5], 30, 32, \[33], 35, 36, 38, 46, 47.
\:\\{y\_offset}, 4, \[5], 30, 32, \[33], 35, 36, 38, 43, 46, 47.
\fin
\:\X25:Can we continue?\X
\U section~24.
\:\X42:Check extremes\X
\U sections~41 and~41.
\:\X46:Compare old with new values\X
\U section~34.
\:\X21, 32:Constants\X
\U section~2.
\:\X41:Convert character raster\X
\U section~40.
\:\X31:Convert \\{chr\_code} into decimal\X
\U section~30.
\:\X43:Find beginning of raster\X
\U section~40.
\:\X6, 7, 8, 10, 16, 23, 29, 33, 39, 45:Global Variables\X
\U section~2.
\:\X11:Open input and output files\X
\U section~2.
\:\X40:Process raster\X
\U section~34.
\:\X28:Read and save character information\X
\U section~50.
\:\X30:Read character header\X
\U section~28.
\:\X34:Read character raster\X
\U section~28.
\:\X24:Read font info\X
\U section~52.
\:\X50:Read \\{chr\_file}\X
\U section~52.
\:\X38:Save offset information\X
\U section~37.
\:\X36:Skip to beginning of character\X
\U section~34.
\:\X5, 9, 22:Types\X
\U section~2.
\:\X37:What is it?\X
\U section~36.
\:\X47:Write directory information to \.{PXL} file\X
\U section~51.
\:\X48:Write font information to \.{PXL} file\X
\U section~51.
\:\X51:Write \\{pxl\_file}\X
\U section~52.
\:\X35:Zero all fields\X
\U section~34.
\con